<template>
  <div id="app">
    <el-container class="box">
      <el-header class="headArea">
        多相机视觉SLAM系统
        <el-avatar>{{ this.userInfo }}</el-avatar>
      </el-header>
      <el-container class="container">
        <el-aside class="menu">
          <el-button class="btn" type="primary" @click="launch">启动SLAM</el-button>
          <el-button class="btn" type="primary" @click="setConfig">设置启动配置</el-button>
          <el-button class="btn" type="primary" @click="stop">停止SLAM</el-button>
          <el-button class="btn" type="primary" @click="lookHistory">历史轨迹记录</el-button>
        </el-aside>
        <el-main class="mainArea">
          <template v-if="history">
            <div v-if="images.length === 0">
              <el-empty
                :image-size="200"
                description="SLAM系统尚未启动"
              ></el-empty>
            </div>
            <div class="imgBox" v-for="(image, index) in images" :key="index">
              <img width="360px" :src="image" :alt="'Camera ' + index" />
              <p>Camera {{ index }}</p>
            </div>
          </template>
          <template v-else>
            <div class="fileList">
              <h1>历史轨迹列表</h1>
              <el-table
                :data="tableData"
                border
                style="width: 100%">
                <el-table-column
                  fixed
                  prop="gTime"
                  label="编号"
                  width="150">
                </el-table-column>
                <el-table-column
                  prop="name"
                  label="文件名">
                </el-table-column>
                <el-table-column
                  fixed="right"
                  label="操作"
                  width="200">
                  <template slot-scope="scope">
                    <el-button @click="handleCheck(scope.row)" type="text" size="small">查看</el-button>
                    <el-button @click="handleDownload(scope.row)" type="text" size="small">下载</el-button>
                    <el-button @click="handleDelete(scope.row)" type="text" size="small">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
              <el-pagination
                background
                layout="prev, pager, next"
                :total="1">
              </el-pagination>
            </div>
          </template>
        </el-main>
      </el-container>
    </el-container>

    <el-dialog title="启动参数配置" :visible.sync="dialogFormVisible">
      <el-form :model="form">
        <el-form-item label="Vocabulary File" :label-width="formLabelWidth">
          <!-- <el-input v-model="form.vocabulary" autocomplete="off" type="file" ref="fileInput" @change="handleFileChange"></el-input> -->
          <button type="button" @click="selectFile(1, 1)">选择文件</button>
          <p v-if="form.vocabulary">已选择文件：{{ form.vocabulary }}</p>
        </el-form-item>
        <el-form-item label="Settings File" :label-width="formLabelWidth">
          <!-- <el-input v-model="form.settings" autocomplete="off" type="file"></el-input> -->
          <button type="button" @click="selectFile(1, 2)">选择文件</button>
          <p v-if="form.settings">已选择文件：{{ form.settings }}</p>
          <!-- {{form.settings}} -->
        </el-form-item>
        <el-form-item label="Calibration Files" :label-width="formLabelWidth">
          <!-- <el-input v-model="form.calibration" autocomplete="off" type="file"></el-input> -->
          <button type="button" @click="selectFile(2, 3)">选择文件夹</button>
          <p v-if="form.calibration">已选择文件夹：{{ form.calibration }}</p>
          <!-- {{form.calibration}} -->
        </el-form-item>
        <el-form-item label="Images" :label-width="formLabelWidth">
          <!-- <el-input v-model="form.images" autocomplete="off" type="file"></el-input> -->
          <button type="button" @click="selectFile(2, 4)">选择文件夹</button>
          <p v-if="form.images">已选择文件夹：{{ form.images }}</p>
          <!-- {{form.images}} -->
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitForm"
          >确 定</el-button
        >
      </div>
    </el-dialog>

    <el-dialog
      :title="trajName"
      :visible.sync="trajVisible"
      width="60%">
      <el-input
        type="textarea"
        :rows="12"
        placeholder="请输入内容"
        v-model="trajText"
        readonly>
      </el-input>
      <span slot="footer" class="dialog-footer">
        <el-button @click="trajVisible = false">取 消</el-button>
        <el-button type="primary" @click="trajVisible = false">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>

export default {
  name: "App",
  components: {},
  data() {
    return {
      images: [], // 用于存储每帧接收的图像数据,
      imgSrc: [
        "/home/zc/slam/data/lafida/outdoor_large_loop/imgs/cam0/img0.png",
        "/home/zc/slam/data/lafida/outdoor_large_loop/imgs/cam0/img0.png",
        "/home/zc/slam/data/lafida/outdoor_large_loop/imgs/cam0/img0.png"
      ],
      dialogFormVisible: false,
      trajVisible: false,
      form: {
        vocabulary: "",
        settings: "",
        calibration: "",
        images: "",
        // 第一个是词汇表文件的路径。第二个是设置文件的路径。第三个是校准文件的路径。第四个是图像的路径。
        // The first is the path to the vocabulary file. The second is the path to the settings file. The third is the path to the calibration files. The fourth is the path to the images. In our example, we could run MultiCol-SLAM
      },
      formLabelWidth: "120px",
      history: true,
      tableData: [],
      trajName: '',
      trajText: '',
      filePath: '',
      userInfo: ''
    };
  },
  methods: {
    launch() {
      const params = {
        vocabulary: this.form.vocabulary,
        settings: this.form.settings,
        calibration: this.form.calibration + '/',
        images: this.form.images
      };
      window.electronAPI.startSLAM(params);
    },
    stop() {
      window.electronAPI.stopSLAM();
    },
    setConfig() {
      this.dialogFormVisible = true;
    },
    submitForm() {
      this.dialogFormVisible = false;
    },
    // 查看历史轨迹数据
    async lookHistory() {
      this.history = false;
      // 从数据库获取轨迹数据
      const trajInfo = await window.electronAPI.getTrajInfo();
      console.log("Traj Info:", trajInfo);
      this.tableData = trajInfo;

    },
    // 查看某一条轨迹数据
    async handleCheck(row) {
      this.trajName = row.name;
      const dir = '/home/zc/slam/code/my-proj/slam/result/';
      const filePath = dir + row.name;
      const result = await window.electronAPI.readTrajFile(filePath);
      this.trajText = result;
      this.trajVisible = true;
    },
    // 下载某一条轨迹数据
    async handleDownload(row) {
      this.trajName = row.name;
      const dir = '/home/zc/slam/code/my-proj/slam/result/';
      const filePath = dir + row.name;
      const result = await window.electronAPI.readTrajFile(filePath);
      console.log("Traj Text:", result);
      this.trajText = result;

      const content = this.trajText;

      // 创建一个 Blob 对象
      const blob = new Blob([content], { type: 'text/plain' });
      // 创建一个指向该 Blob 的 URL
      const url = URL.createObjectURL(blob);

      // 创建并点击下载链接
      const a = document.createElement('a');
      a.href = url;
      a.download = row.name;
      document.body.appendChild(a);
      a.click();

      // 在下载后释放 Blob URL
      setTimeout(() => {
        URL.revokeObjectURL(url);
        document.body.removeChild(a);
      }, 0);

    },
    // 删除某一条轨迹数据
    async handleDelete(row) {
      const gTime = row.gTime;
      const name = row.name;
      const result = await window.electronAPI.deleteTrajFile(name, gTime);
      console.log(result);
      
      this.tableData = result;
    },
    // 选择文件
    async selectFile(item, num) {
      if (item === 1) {
        const path = await window.electronAPI.openFileDialog();
        if (path) {
          if (num === 1) {
            this.form.vocabulary = path;
          } else if (num === 2) {
            this.form.settings = path;
          }
        }
      } else {
        const path = await window.electronAPI.openFilesDialog();
        if (path) {
          if (num === 3) {
            this.form.calibration = path;
          } else if (num === 4) {
            this.form.images = path;
          }
        }
      }
    },

    // 获取用户信息
    async getUserInfo() {
      const user = await window.electronAPI.getUserInfo();
      console.log("User Info:", user);
      this.userInfo = user[0].name;
    }

  },
  created() {
    
  },
  mounted() {
    // 建立 WebSocket 连接
    this.websocket = new WebSocket("ws://127.0.0.1:8765");

    // 接收图像数据
    this.websocket.onmessage = (event) => {
      try {
        const receivedData = JSON.parse(event.data); // 解析 JSON 数据

        // 如果数据格式正确，且是一个数组
        if (Array.isArray(receivedData)) {
          this.images = receivedData.map(
            (imgBase64) => `data:image/jpeg;base64,${imgBase64}`
          );
        }
      } catch (error) {
        console.error("接收的 WebSocket 数据无法解析", error);
      }
    };

    // 处理连接关闭
    this.websocket.onclose = () => {
      console.log("WebSocket connection closed");
    };

    // 获取用户信息
    this.getUserInfo();

  },
  beforeDestroy() {
    // 在组件销毁前关闭 WebSocket
    if (this.websocket) {
      this.websocket.close();
    }
  },
};
</script>

<style>
html {
  width: 100vw;
  margin: 0;
  padding: 0;
  height: 100vh;
}

#app {
  height: 95vh;
  width: 100%;
  /* display: flex; */
  /* flex-direction: column; */
  /* flex: 1; */
}

.box {
  height: 100%;
  width: 100%;
  display: flex;
}

.container {
  flex: 1;
  display: flex;
  height: 100%;
  width: 100%;
}

.headArea {
  height: 60px;
  line-height: 60px;
  font-size: 24px;
  font-family: 'Courier New', Courier, monospace;
  box-shadow: 0 15px 15px #f0f2f5;
  z-index: 9999;
  display: flex;
  justify-content: space-between;
  align-items:center;
}

.menu {
  background-color: #f0f2f5;
  padding: 16px 0;
  max-width: 160px;
  display: flex;
  flex-direction: column;
  align-items: baseline;
  padding-top: 30px;
}

.menu .btn {
  margin-bottom: 16px;
  width: 100px;
  box-sizing: content-box;
  text-align: center;
}

.mainArea {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}

.imgBox {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  width: 360px;
  height: auto;
}

.fileList {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
</style>
